
local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddSoundEmitter()
    inst.entity:AddDynamicShadow()
    inst.entity:AddNetwork()

    MakeGhostPhysics(inst, 1, .5)

    inst.DynamicShadow:SetSize(1.5, .75)

    inst.Transform:SetFourFaced()
    inst.Transform:SetScale(.75, .75, .75)

    inst.AnimState:SetBank("bat")
    inst.AnimState:SetBuild("bat_basic")

    -- inst:AddTag("cavedweller")
    -- inst:AddTag("monster")
    -- inst:AddTag("hostile")
    -- inst:AddTag("bat")
    -- inst:AddTag("scarytoprey")
    inst:AddTag("flying")
    -- inst:AddTag("ignorewalkableplatformdrowning")
    inst:AddTag("monster_npc")
    inst:AddTag("trader")
    inst:AddTag("alltrader") ---
    inst:AddTag("companion")

    MakeInventoryFloatable(inst)

    inst.entity:SetPristine()

    ---------------------------------------------------------------------------------------------
    -- talker 组件   net_bool 帮助处理偏移
    -- local TALLER_TALKER_OFFSET = Vector3(0, -700, 0)
    local DEFAULT_TALKER_OFFSET = Vector3(0, -700, 0)
    inst:AddComponent("talker")
    inst.components.talker.offset = DEFAULT_TALKER_OFFSET
    inst.components.talker.Say_old = inst.components.talker.Say
    inst.components.talker.Say = function(self,...)
        self:Say_old(...)
        if self.inst.sg then
            self.inst.sg:GoToState("taunt")
        end
    end


    if not TheWorld.ismastersim then ---------------------------------------------------------------------------------------------
        return inst
    end

    inst:AddComponent("locomotor")
    inst.components.locomotor:EnableGroundSpeedMultiplier(false)
    inst.components.locomotor:SetTriggersCreep(false)
    inst.components.locomotor.walkspeed = TUNING.BAT_WALK_SPEED
    inst.components.locomotor.pathcaps = { allowocean = true }

    inst:SetStateGraph("SGbat")

    --------------------------------------------------------------------------------------------------
    -- -- 保护组件
    inst:AddComponent("combat")
    inst:AddComponent("health")
    inst.components.health:SetMaxHealth(100)

    inst.components.health.DoDelta_old = inst.components.health.DoDelta
    inst.components.health.DoDelta = function(self,num,...)
        self.currenthealth = 100
        local ret = { self:DoDelta_old(-0.1,...) }
        self.currenthealth = 100
        return unpack(ret)
    end    
    inst.components.health.OnUpdate_old = inst.components.health.OnUpdate
    inst.components.health.OnUpdate = function(self,...)
        self.currenthealth = 100
        self:OnUpdate_old(...)
    end
    inst:ListenForEvent("attacked",function()
        inst:AddTag("INLIMBO")
        inst:DoTaskInTime(5,function()
            inst:RemoveTag("INLIMBO")
        end)
    end)
    ---------------------------------------------------------------------------------------------------
    inst:AddComponent("npc_base_lib")
    inst:AddComponent("npc_everything_data")



    inst:AddComponent("lootdropper")

    inst:AddComponent("debuffable")

    inst:AddComponent("named")
    --STRINGS.PIGNAMES -- STRINGS.CROWNAMES
    inst:DoTaskInTime(0.1,function()        
        -- local function firstToUpper(str)
        --     return (str:gsub("^%l",string.upper))
        -- end
        -- inst.components.named:SetName(firstToUpper(inst.prefab_base))
        -- local language = inst.npc_base_lib:Get_Language()
        -- if language == "ch" then
        --     STRINGS.CHARACTERS.GENERIC.DESCRIBE[string.upper(inst.prefab)] = "友好的蝙蝠"
        -- else
        --     STRINGS.CHARACTERS.GENERIC.DESCRIBE[string.upper(inst.prefab)] = "Another adventurer"
        -- end
        
        inst.components.named.possiblenames = inst.npc_base_lib:Get_Names()
        inst.components.named:PickNewName()
    end)



    

    -----------------------------------------------------------------------------------------------------------
    -------------------------------------------------------------------------
    -- 物品栏 和物品接收 相关
    -- 衣服类装备 普遍没有 com_tradable,无法被给到NPC。需要特殊手段添加给物品
    inst:AddComponent("container")
    inst.components.container.canbeopened = false
    inst.components.container.numslots = 9

    local function ShouldAcceptItem(inst, item)
        return item.components.inventoryitem ~= nil
    end
    local function OnGetItem(inst, giver, item)
        print("OnGetItem ,Giver :",giver,item)
    end
    local function abletoaccepttest(inst,item,giver)
        if item.components.inventoryitem ~= nil then
            return true
        end
    end
    inst:AddComponent("trader")
    -- inst.components.trader:SetAcceptTest(ShouldAcceptItem)
    -- inst.components.trader.onaccept = OnGetItem
    inst.components.trader.deleteitemonaccept = true
    -- inst.components.trader:SetAbleToAcceptTest(abletoaccepttest)

    -----------------------------------------------------------------------------------------------------------
    -- -- player link
    inst:ListenForEvent("player_link",function(inst,tar_player)
        inst.__link_player = tar_player
        inst.npc_base_lib:Set_Linked_Player(tar_player)
        if tar_player and tar_player:HasTag("player") then
            tar_player.__link_npc = inst
        end
        print("NPC",inst.prefab,"Link Player",tar_player)
    end)

    inst:ListenForEvent("player_unlink",function()
        if inst.__link_player then
            inst.__link_player.__link_npc = nil
        end
    end)

    inst:DoTaskInTime(0.1,function()
        if inst.Ready == true then
            return
        end

        if inst.__link_player == nil then
            inst:Remove()
            print("warning : npc.__link_player == nil , inst:Remove() ")
        else
            print("npc create and  link succeed")
        end
    end)

    function inst:GetPlayer()
        return self.__link_player
    end

    ---------------------------------------------------------------------------------------------------------------

    return inst
end

return Prefab("monster_npc_bat", fn)
